﻿Imports System.Xml.Serialization
Imports Framework.Data

Namespace Commands
    Public Class GetAvailableParts
        Inherits Framework.Net.CommandBase

        Private Const mRequestCode As String = "GetAvailablePartsRequest"
        Private Const mReplyCode As String = "GetAvailablePartsReply"

        Public Sub New()
            MyBase.New(mRequestCode, mReplyCode)
        End Sub

        Public Class Request
            Public Files As New Generic.List(Of FileSignature)
            Public IsRefresh As Boolean

            Public Class FileSignature
                <XmlAttribute()> Public Size As Long
                <XmlText()> Public SHA512Hash As String
            End Class
        End Class

        Public Class Reply
            Public AvailableParts As New Generic.List(Of FileAvailablitySummary)
        End Class

        Friend Shared Function SendRequest(ByVal node As Framework.Net.Node, ByVal files As Generic.List(Of Request.FileSignature), ByVal isRefresh As Boolean, ByVal callback As ReplyDelegate, ByVal invokeCallbackOnMainGuiThread As Boolean) As Integer
            Dim clsRequest As New Request
            clsRequest.Files = files
            clsRequest.IsRefresh = isRefresh

            Dim iMessageId As Integer = Framework.Net.Manager.GetNextMessageId
            RegisterCallback(iMessageId, callback, invokeCallbackOnMainGuiThread)
            node.SendCommandMessageAsync(iMessageId, mRequestCode, Framework.Serialization.ToXmlBytes(clsRequest))
            Return iMessageId
        End Function

        Public Delegate Sub ReplyDelegate(ByVal inReplyToMessageId As Integer, ByVal node As Framework.Net.Node, ByVal reply As Reply)
        Public Overrides Sub HandleReply(ByVal envelope As Framework.Net.MessageEnvelope)
            Dim clsReply As Reply = Framework.Serialization.FromXmlBytes(Of Reply)(envelope.Message.Message)
            For Each clsFA As FileAvailablitySummary In clsReply.AvailableParts
                clsFA.AtBuddyId = envelope.Node.Buddy.Id
            Next
            InvokeCallback(envelope.Message.InReplyToId, envelope.Node, clsReply)
        End Sub

        Public Overrides Sub HandleRequest(ByVal envelope As Framework.Net.MessageEnvelope)
            Dim clsRequest As Request = Framework.Serialization.FromXmlBytes(Of Request)(envelope.Message.Message)

            Dim clsReply As New Reply

            If clsRequest.Files IsNot Nothing Then
                'first, look for complete files
                Dim aNotFound As New Generic.List(Of Request.FileSignature)
                For Each clsFile As Request.FileSignature In clsRequest.Files
                    Dim clsSharedFile As Entities.SharedItemFile
                    clsSharedFile = EntityHandlers.SharedItemsFiles.GetBySHA512HashAndSizeNotOrphaned(clsFile.SHA512Hash, clsFile.Size)
                    If envelope.Node.BuddyKeyMaster.IsGranted(clsSharedFile) Then
                        Dim clsAvailability As New FileAvailablitySummary
                        clsAvailability.Parts = TransferEngine.Manager.CreatePartStatusArray(clsSharedFile.Size, Entities.Downloads.PartStatus.Complete)
                        clsAvailability.Size = clsSharedFile.Size
                        clsAvailability.SHA512Hash = clsSharedFile.SHA512Hash
                        clsReply.AvailableParts.Add(clsAvailability)
                    Else
                        aNotFound.Add(clsFile)
                    End If
                Next
                'now, look to see if we're downloading these files ourselves
                If envelope.Node.BuddyKeyMaster.IsGranted(Settings.IncomingDownloadsGrantedToSecurityGroupIds) Then
                    For Each clsFile As Request.FileSignature In aNotFound
                        Dim clsDownloadingFile As Entities.Downloads.File = EntityHandlers.DownloadsFiles.GetBySHA512HashAndSize(clsFile.SHA512Hash, clsFile.Size)
                        If clsDownloadingFile IsNot Nothing Then
                            If clsDownloadingFile.PartsCompleted > 0 Then
                                Dim clsAvailability As New FileAvailablitySummary
                                'clsAvailability.Name = clsDownloadingFile.Name
                                clsAvailability.Parts = clsDownloadingFile.PartStatuses
                                clsAvailability.Size = clsDownloadingFile.Size
                                clsAvailability.SHA512Hash = clsDownloadingFile.SHA512Hash
                                clsReply.AvailableParts.Add(clsAvailability)
                            End If
                        End If
                    Next

                    'ok, now we update the file subscription table to represent what the buddy
                    'is looking for at the moment
                    Using t As New TransactionScope
                        If clsRequest.IsRefresh Then
                            EntityHandlers.DownloadsFileSubscriptions.DeleteAllByBuddyId(envelope.Node.Buddy.Id, t)
                        End If
                        For Each clsFile As Request.FileSignature In clsRequest.Files
                            Dim clsSub As New Entities.Downloads.FileSubscription
                            clsSub.BuddyId = envelope.Node.Buddy.Id
                            clsSub.SHA512Hash = clsFile.SHA512Hash
                            clsSub.Size = clsFile.Size
                            EntityHandlers.DownloadsFileSubscriptions.Save(clsSub, t)
                        Next

                        t.Complete()
                    End Using
                End If
            End If
            envelope.Node.SendReplyCommandMessageAsync(envelope, ReplyCode, Framework.Serialization.ToXmlBytes(clsReply))
        End Sub

    End Class



End Namespace


